import java.util.ArrayList;

import java.util.HashMap;
import java.util.Map.Entry;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;


public class Capabilities extends Observer{
	/*********Singleton Pattern *********/
	static private Capabilities instance = null;
	static Capabilities getInstance() {
		if(instance == null){
			instance= new Capabilities();
		}
		return instance;
	}
	private Capabilities() {
		super();
	}
	/************************************/
	
	HashMap<String, Movement> movements = new HashMap<String, Movement>();
	HashMap<String, Attack> attacks = new HashMap<String, Attack>();
	
	/**************GUI**************/
	Composite toolbar = null;
	
	//-------Capabilities Bar------//
	ExpandBar capabilitiesBar=null;
	ExpandItem capabilitiesBarAttackItem = null;
	GridLayout capabilitiesBarAttackLayout = null;
	ExpandItem capabilitiesBarMotorItem = null;
	GridLayout capabilitiesBarMotorLayout = null;
	//---------RobotForm----------//
	Label robotNameLabel = null;
	Label robotAvatarLabel = null;
	Label robotPosLabel = null;
	Label robotCreditsLabel = null;
	Label robotLifeLabel = null;
	Text robotNameText = null;
	Text robotAvatarText = null;
	Text robotXText = null;
	Text robotYText = null;
	Text robotCreditsText = null;
	Text robotLifeText= null;
	//---------Form Buttons--------//
	Button createButton = null;
	Button applyButton = null;
	Button pauseButton = null;
	
	Movement selectedMovement = null;
	Attack selectedAttack = null;
	/******************************/
	
	public void addMovement(Movement movement){
		if(movement != null)
			movements.put(movement.name,movement);
	}
	
	public void addAttack(Attack attack){
		if(attack != null)
			attacks.put(attack.name,attack);
	}
	
	public void deleteMovement(String movementKey){
		Movement movement= movements.get(movementKey);
		if(movement != null){
			movements.remove(movementKey);
			movement.button.dispose();
		}
	}
	
	public void deleteAttack(String attackKey){
		Attack attack = attacks.get(attackKey);
		if(attack != null){
			attacks.remove(attackKey);
			attack.button.dispose();
		}
	}

	public void startGUI(Composite parent, int x, int y, int width, int height){
		toolbar = new Composite(parent, SWT.NONE);
		toolbar.setLayout(new GridLayout());
		toolbar.setLayoutData(new GridData());
		toolbar.setBounds(x, y, width, height);
		capabilitiesBar = new ExpandBar(toolbar, SWT.V_SCROLL);
		//Robot form
		int labelLeft = 15;
		int textLeft = 65;
		int robotY = 20;
		int avatarY = 50;
		int fieldHeight = 20;
		int textWidth = 100;
		int labelWidth = 40;
		int posY = 80;
		int posTextWidth = 30;
		int creditsY = 110;
		int lifeY = 140;
		
		robotNameLabel = new Label(toolbar, SWT.NONE);
		robotNameLabel.setText("Robot");
		robotNameLabel.setBounds(labelLeft, robotY, labelWidth, fieldHeight);
		robotNameText = new Text(toolbar, SWT.SINGLE);
		robotNameText.setBounds(textLeft, robotY, textWidth, fieldHeight);
		
		robotAvatarLabel = new Label(toolbar, SWT.NONE);
		robotAvatarLabel.setText("Avatar");
		robotAvatarLabel.setBounds(labelLeft, avatarY, labelWidth, fieldHeight);
		robotAvatarText = new Text(toolbar, SWT.SINGLE);
		robotAvatarText.setBounds(textLeft, avatarY, textWidth, fieldHeight);
		
		robotPosLabel = new Label(toolbar, SWT.NONE);
		robotPosLabel.setText("Position");
		robotPosLabel.setBounds(labelLeft, posY, labelWidth, fieldHeight);
		robotXText = new Text(toolbar, SWT.SINGLE);
		robotXText.setBounds(textLeft, posY, posTextWidth, fieldHeight);
		robotYText = new Text(toolbar, SWT.SINGLE);
		robotYText.setBounds(textLeft+posTextWidth+10, posY, posTextWidth, fieldHeight);
		
		robotCreditsLabel = new Label(toolbar, SWT.NONE);
		robotCreditsLabel.setText("Credits");
		robotCreditsLabel.setBounds(labelLeft, creditsY, labelWidth, fieldHeight);
		robotCreditsText = new Text(toolbar, SWT.SINGLE);
		robotCreditsText.setBounds(textLeft, creditsY, textWidth, fieldHeight);
		
		robotLifeLabel = new Label(toolbar, SWT.NONE);
		robotLifeLabel.setText("Life");
		robotLifeLabel.setBounds(labelLeft, lifeY, labelWidth, fieldHeight);
		robotLifeText = new Text(toolbar, SWT.SINGLE);
		robotLifeText.setBounds(textLeft, lifeY, textWidth, fieldHeight);
		
		//Attack Bar
		Composite composite = new Composite (capabilitiesBar, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom=8;
		layout.verticalSpacing = 2;
		composite.setLayout(layout);
		
		capabilitiesBarAttackItem = new ExpandItem (capabilitiesBar, SWT.NONE, 0);
		capabilitiesBarAttackItem.setText("Attacks");
		capabilitiesBarAttackItem.setControl(composite);
		setAttackBar();

		//MotorBar
		composite = new Composite (capabilitiesBar, SWT.NONE);
		layout = new GridLayout();
		layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom=8;
		layout.verticalSpacing = 2;
		composite.setLayout(layout);
		
		capabilitiesBarMotorItem = new ExpandItem (capabilitiesBar, SWT.NONE, 1);
		capabilitiesBarMotorItem.setText("Motors");
		capabilitiesBarMotorItem.setControl(composite);
		setMovementBar();
		
		//Form buttons
		createButton = new Button(toolbar, SWT.PUSH);
		createButton.setText("Create");
		createButton.setBounds(20, 500, 80, 25);
		createButton.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				try{
					int x = Integer.parseInt(robotXText.getText());
					int y =  Integer.parseInt(robotYText.getText());
					String robotName = robotNameText.getText();
					String filename = robotAvatarText.getText();
					Robot robot = Map.getInstance().createRobot(x, y, robotName, filename);	
					robot.movement = Capabilities.getInstance().selectedMovement;
					robot.attack = Capabilities.getInstance().selectedAttack;
				}
				catch(Exception e){
					System.out.println(e.getMessage());
					//TODO mostrar mensagem de erro
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		applyButton = new Button(toolbar, SWT.PUSH);
		applyButton.setText("Apply");
		applyButton.setBounds(95, 500, 80, 25);
		applyButton.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				try{
					//parse
					int x = Integer.parseInt(robotXText.getText());
					int y =  Integer.parseInt(robotYText.getText());
					String robotName = robotNameText.getText();
					String filename = robotAvatarText.getText();
					//get robot to update
					Robot robot = Map.getInstance().selectedRobot;
					//update robot
					robot.name = robotName;
					robot.setAvatarImage(filename);
					robot.movement = Capabilities.getInstance().selectedMovement;
					robot.attack = Capabilities.getInstance().selectedAttack;

				}
				catch(Exception e){
					System.out.println(e.getMessage());
					//TODO mostrar mensagem de erro
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		pauseButton = new Button(toolbar, SWT.TOGGLE);
		pauseButton.setText("Play");
		pauseButton.setBounds(50, 540, 100, 25);
		pauseButton.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				if(pauseButton.getSelection())
					pauseButton.setText("Pause");
				else{
					pauseButton.setText("Play");
				}
				Map.getInstance().pause = !Map.getInstance().pause;
				
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
		int capabilitiesBarY= robotY+lifeY+fieldHeight;
		capabilitiesBar.setSpacing(6);
		capabilitiesBar.setBounds(0, capabilitiesBarY, width, 300);
		
	}


	private void setAttackBar() {
		if(capabilitiesBarAttackItem!=null){
			Composite barComposite = (Composite)capabilitiesBarAttackItem.getControl();
			if(barComposite!=null){
				for(Entry<String,Attack> entry: attacks.entrySet()){
					Behaviour b = entry.getValue();
					b.startGUI(barComposite);
				}
				//resize bar
				capabilitiesBarAttackItem.setHeight(barComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			}
			else{
				System.err.println("barItem doesn't have control");
			}
		}
		else{
			System.err.println("capabilitiesBarAttackItem is null");
		}
	}
	
	private void setMovementBar() {
		if(capabilitiesBarMotorItem!=null){
			Composite barComposite = (Composite)capabilitiesBarMotorItem.getControl();
			if(barComposite!=null){
				//iterate through all attacks
				for(Entry<String,Movement> entry: movements.entrySet()){
					Behaviour b = entry.getValue();
					b.startGUI(barComposite);
				}
				//resize bar
				capabilitiesBarMotorItem.setHeight(barComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
			}
			else{
				System.err.println("barItem doesn't have control");
			}
		}
		else{
			System.err.println("capabilitiesBarAttackItem is null");
		}
	}
	@Override
	public void notifyAttack(String name, String path, String action) {
		if(action.equals("add")){
			Attack a = new Attack(name, path);
			addAttack(a);
		}
		else if(action.equals("modify")){
			Attack attack = attacks.get(name);
			if(attack != null){
				attack.reload();
			}
		}
		else if(action.equals("delete")){
			deleteAttack(name);
		}
		setAttackBar();
	}
	@Override
	public void notifyMovement(String name, String path, String action) {
		if(action.equals("add")){
			Movement m = new Movement(name, path);
			addMovement(m);
		}
		else if(action.equals("modify")){
			Movement movement= movements.get(name);
			if(movement != null){
				movement.reload();
			}
		}
		else if(action.equals("delete")){
			deleteMovement(name);
		}
		setMovementBar();
	}
}
